const httpStatus = require('http-status');
const ApiError = require('../utils/ApiError');
const DietRecord = require('../models/dietRecord.model');
const NutritionGoal = require('../models/nutritionGoal.model');
const logger = require('../config/logger');
const mongoose = require('mongoose');
const moment = require('moment');

/**
 * 获取热量摄入趋势数据
 * @param {Object} options - 查询选项
 * @param {string} options.userId - 用户ID
 * @param {string} options.period - 时间段：7天，30天，90天
 * @returns {Promise<Object>} 热量摄入趋势数据
 */
const getCaloriesTrend = async (options) => {
  const { userId, period = '7' } = options;
  
  logger.info(`【营养分析】获取用户 ${userId} 的热量摄入趋势，周期: ${period}`);
  
  // 根据周期确定起始日期
  const days = parseInt(period, 10);
  const startDate = moment().subtract(days, 'days').startOf('day').toDate();
  const endDate = moment().endOf('day').toDate();
  
  logger.debug(`【营养分析】查询时间范围: ${startDate} 至 ${endDate}`);
  
  try {
    // 查询用户的营养目标
    const nutritionGoal = await NutritionGoal.findOne({ userId, isDeleted: { $ne: true } });
    const caloriesGoal = nutritionGoal ? nutritionGoal.caloriesGoal : 2000; // 默认目标2000卡
    
    // 查询用户在指定时间段内的饮食记录，按日期分组计算总热量
    const result = await DietRecord.aggregate([
      {
        $match: {
          userId: new mongoose.Types.ObjectId(userId),
          dateTime: { $gte: startDate, $lte: endDate },
          isDeleted: { $ne: true }
        }
      },
      {
        $group: {
          _id: { $dateToString: { format: '%Y-%m-%d', date: '$dateTime' } },
          totalCalories: { $sum: '$totalCalories' }
        }
      },
      {
        $sort: { _id: 1 } // 按日期升序排序
      },
      {
        $project: {
          _id: 0,
          date: '$_id',
          calories: '$totalCalories'
        }
      }
    ]);
    
    // 填充没有数据的日期（设置为0卡路里）
    const filledResult = [];
    for (let i = 0; i < days; i++) {
      const date = moment().subtract(days - i - 1, 'days').format('YYYY-MM-DD');
      const existingData = result.find(item => item.date === date);
      filledResult.push({
        date,
        calories: existingData ? existingData.calories : 0
      });
    }
    
    // 计算标签（日期格式为MM-DD）和数据集
    const labels = filledResult.map(item => moment(item.date).format('MM-DD'));
    const datasets = filledResult.map(item => item.calories);
    
    // 计算总热量和平均热量
    const total = datasets.reduce((sum, val) => sum + val, 0);
    const average = Math.round(total / days);
    
    // 找出最高和最低卡路里摄入日
    let highestIndex = 0;
    let lowestIndex = 0;
    
    for (let i = 1; i < datasets.length; i++) {
      if (datasets[i] > datasets[highestIndex]) {
        highestIndex = i;
      }
      if (datasets[i] < datasets[lowestIndex] || (datasets[i] === 0 && datasets[lowestIndex] === 0 && i === lowestIndex)) {
        lowestIndex = i;
      }
    }
    
    const highest = {
      value: datasets[highestIndex],
      date: filledResult[highestIndex].date
    };
    
    const lowest = {
      value: datasets[lowestIndex],
      date: filledResult[lowestIndex].date
    };
    
    // 计算趋势
    const calculateTrend = (values) => {
      if (values.length < 3) return 'insufficient_data';
      
      // 将数据分成前半部分和后半部分来比较趋势
      const firstHalf = values.slice(0, Math.floor(values.length / 2));
      const secondHalf = values.slice(Math.floor(values.length / 2));
      
      const firstHalfAvg = firstHalf.reduce((sum, val) => sum + val, 0) / firstHalf.length;
      const secondHalfAvg = secondHalf.reduce((sum, val) => sum + val, 0) / secondHalf.length;
      
      const difference = secondHalfAvg - firstHalfAvg;
      const threshold = firstHalfAvg * 0.05; // 5%变动阈值
      
      if (Math.abs(difference) < threshold) return 'steady';
      return difference > 0 ? 'increasing' : 'decreasing';
    };
    
    const trending = calculateTrend(datasets);
    
    // 构建符合接口规范的返回数据结构
    const trendData = {
      labels,
      datasets,
      goal: caloriesGoal,
      average,
      total,
      highest,
      lowest,
      trending
    };
    
    logger.info(`【营养分析】成功获取热量趋势数据，共 ${labels.length} 天`);
    return trendData;
  } catch (error) {
    logger.error(`【营养分析】获取热量趋势失败: ${error.message}`);
    throw error;
  }
};

/**
 * 获取营养素比例数据
 * @param {Object} options - 查询选项
 * @param {string} options.userId - 用户ID
 * @param {string} options.period - 时间段：today, week, month
 * @returns {Promise<Object>} 营养素比例数据
 */
const getNutrientRatio = async (options) => {
  const { userId, period = 'today' } = options;
  
  logger.info(`【营养分析】获取用户 ${userId} 的营养素比例，周期: ${period}`);
  
  // 确定时间范围
  let startDate, endDate;
  if (period === 'today') {
    startDate = moment().startOf('day').toDate();
    endDate = moment().endOf('day').toDate();
  } else if (period === 'week') {
    startDate = moment().subtract(7, 'days').startOf('day').toDate();
    endDate = moment().endOf('day').toDate();
  } else if (period === 'month') {
    startDate = moment().subtract(30, 'days').startOf('day').toDate();
    endDate = moment().endOf('day').toDate();
  }
  
  try {
    // 查询用户在指定时间段内的营养素摄入总量
    const result = await DietRecord.aggregate([
      {
        $match: {
          userId: new mongoose.Types.ObjectId(userId),
          dateTime: { $gte: startDate, $lte: endDate },
          isDeleted: { $ne: true }
        }
      },
      {
        $group: {
          _id: null,
          totalProtein: { $sum: '$totalNutrition.protein' },
          totalFat: { $sum: '$totalNutrition.fat' },
          totalCarbs: { $sum: '$totalNutrition.carbs' }
        }
      },
      {
        $project: {
          _id: 0,
          protein: '$totalProtein',
          fat: '$totalFat',
          carbs: '$totalCarbs'
        }
      }
    ]);
    
    // 如果没有数据，设置默认值
    let ratioData;
    if (result.length === 0) {
      ratioData = {
        protein: 0,
        fat: 0,
        carbs: 0
      };
    } else {
      ratioData = result[0];
    }
    
    // 计算总量
    const total = ratioData.protein + ratioData.fat + ratioData.carbs;
    
    // 计算比例（如果总量为0，设置默认比例）
    let ratios;
    if (total === 0) {
      ratios = {
        protein: { percentage: 25, color: '#1AE5BE' },
        fat: { percentage: 30, color: '#FFA726' },
        carbs: { percentage: 45, color: '#42A5F5' }
      };
    } else {
      ratios = {
        protein: { 
          percentage: Math.round((ratioData.protein / total) * 100),
          color: '#1AE5BE'
        },
        fat: { 
          percentage: Math.round((ratioData.fat / total) * 100),
          color: '#FFA726'
        },
        carbs: { 
          percentage: Math.round((ratioData.carbs / total) * 100),
          color: '#42A5F5'
        }
      };
      
      // 调整百分比，确保总和为100%
      const totalPercentage = ratios.protein.percentage + ratios.fat.percentage + ratios.carbs.percentage;
      if (totalPercentage !== 100) {
        // 将差值加到最大的一项上
        let max = 'protein';
        if (ratios.fat.percentage > ratios[max].percentage) max = 'fat';
        if (ratios.carbs.percentage > ratios[max].percentage) max = 'carbs';
        
        ratios[max].percentage += (100 - totalPercentage);
      }
    }
    
    logger.info(`【营养分析】成功获取营养素比例数据: 蛋白质=${ratios.protein.percentage}%, 脂肪=${ratios.fat.percentage}%, 碳水=${ratios.carbs.percentage}%`);
    return ratios;
  } catch (error) {
    logger.error(`【营养分析】获取营养素比例失败: ${error.message}`);
    throw error;
  }
};

/**
 * 获取营养素详情数据
 * @param {Object} options - 查询选项
 * @param {string} options.userId - 用户ID
 * @param {string} options.period - 时间段：today, week, month
 * @returns {Promise<Object>} 营养素详情数据
 */
const getNutrientDetails = async (options) => {
  const { userId, period = 'today' } = options;
  
  logger.info(`【营养分析】获取用户 ${userId} 的营养素详情，周期: ${period}`);
  
  // 确定时间范围
  let startDate, endDate;
  if (period === 'today') {
    startDate = moment().startOf('day').toDate();
    endDate = moment().endOf('day').toDate();
  } else if (period === 'week') {
    startDate = moment().subtract(7, 'days').startOf('day').toDate();
    endDate = moment().endOf('day').toDate();
  } else if (period === 'month') {
    startDate = moment().subtract(30, 'days').startOf('day').toDate();
    endDate = moment().endOf('day').toDate();
  }
  
  try {
    // 获取用户的营养目标
    const nutritionGoal = await NutritionGoal.findOne({ userId, isDeleted: { $ne: true } });
    
    // 查询用户在指定时间段内的营养素摄入总量
    const result = await DietRecord.aggregate([
      {
        $match: {
          userId: new mongoose.Types.ObjectId(userId),
          dateTime: { $gte: startDate, $lte: endDate },
          isDeleted: { $ne: true }
        }
      },
      {
        $group: {
          _id: null,
          totalProtein: { $sum: '$totalNutrition.protein' },
          totalFat: { $sum: '$totalNutrition.fat' },
          totalCarbs: { $sum: '$totalNutrition.carbs' },
          totalFiber: { $sum: '$totalNutrition.fiber' },
          totalSugar: { $sum: '$totalNutrition.sugar' },
          totalSodium: { $sum: '$totalNutrition.sodium' }
        }
      },
      {
        $project: {
          _id: 0,
          protein: '$totalProtein',
          fat: '$totalFat',
          carbs: '$totalCarbs',
          fiber: '$totalFiber',
          sugar: '$totalSugar',
          sodium: '$totalSodium'
        }
      }
    ]);
    
    // 如果没有数据，设置默认值
    const current = result.length > 0 ? result[0] : {
      protein: 0,
      fat: 0,
      carbs: 0,
      fiber: 0,
      sugar: 0,
      sodium: 0
    };
    
    // 设置默认目标值（如果没有用户目标）
    const target = nutritionGoal ? {
      protein: nutritionGoal.dailyProtein || 90,
      fat: nutritionGoal.dailyFat || 70,
      carbs: nutritionGoal.dailyCarbs || 280,
      fiber: nutritionGoal.dailyFiber || 30,
      sugar: nutritionGoal.dailySugar || 50,
      sodium: nutritionGoal.dailySodium || 2300
    } : {
      protein: 90,
      fat: 70,
      carbs: 280,
      fiber: 30,
      sugar: 50,
      sodium: 2300
    };
    
    // 为时间段调整目标值
    if (period === 'week') {
      Object.keys(target).forEach(key => {
        target[key] *= 7;
      });
    } else if (period === 'month') {
      Object.keys(target).forEach(key => {
        target[key] *= 30;
      });
    }
    
    // 构建营养素详情数据
    const nutrients = [
      { 
        name: '蛋白质', 
        current: Math.round(current.protein), 
        target: target.protein, 
        unit: 'g',
        color: '#1AE5BE'
      },
      { 
        name: '脂肪', 
        current: Math.round(current.fat), 
        target: target.fat, 
        unit: 'g',
        color: '#FFA726'
      },
      { 
        name: '碳水化合物', 
        current: Math.round(current.carbs), 
        target: target.carbs, 
        unit: 'g',
        color: '#42A5F5'
      },
      { 
        name: '膳食纤维', 
        current: Math.round(current.fiber), 
        target: target.fiber, 
        unit: 'g',
        color: '#9C27B0'
      },
      { 
        name: '糖', 
        current: Math.round(current.sugar), 
        target: target.sugar, 
        unit: 'g',
        color: '#F44336'
      },
      { 
        name: '钠', 
        current: Math.round(current.sodium), 
        target: target.sodium, 
        unit: 'mg',
        color: '#FF9800'
      }
    ];
    
    logger.info(`【营养分析】成功获取营养素详情数据，共 ${nutrients.length} 项`);
    return { nutrients };
  } catch (error) {
    logger.error(`【营养分析】获取营养素详情失败: ${error.message}`);
    throw error;
  }
};

/**
 * 获取营养分析结果
 * @param {Object} options - 查询选项
 * @param {string} options.userId - 用户ID
 * @param {string} options.period - 时间段：today, week, month
 * @returns {Promise<Object>} 营养分析结果
 */
const getNutritionAnalysis = async (options) => {
  const { userId, period = 'week' } = options;
  logger.info(`【营养分析】开始获取用户 ${userId} 的营养分析数据`);
  
  try {
    // 确定时间范围
    let startDate, endDate;
    if (period === 'today') {
      startDate = moment().startOf('day').toDate();
      endDate = moment().endOf('day').toDate();
    } else if (period === 'week') {
      startDate = moment().subtract(7, 'days').startOf('day').toDate();
      endDate = moment().endOf('day').toDate();
    } else if (period === 'month') {
      startDate = moment().subtract(30, 'days').startOf('day').toDate();
      endDate = moment().endOf('day').toDate();
    }
    
    // 获取用户的营养目标
    const nutritionGoal = await NutritionGoal.findOne({ userId, isDeleted: { $ne: true } });
    
    // 查询用户在指定时间段内的饮食记录
    const dietRecords = await DietRecord.find({
      userId: new mongoose.Types.ObjectId(userId),
      dateTime: { $gte: startDate, $lte: endDate },
      isDeleted: { $ne: true }
    }).sort({ dateTime: 1 });
    
    // 获取热量趋势和营养素比例
    const [caloriesTrend, nutrientRatio] = await Promise.all([
      getCaloriesTrend({ userId, period: period === 'today' ? '1' : period === 'week' ? '7' : '30' }),
      getNutrientRatio({ userId, period })
    ]);
    
    // 计算总卡路里和营养素总量
    let totalCalories = 0;
    let totalNutrition = {
      protein: 0,
      fat: 0,
      carbohydrate: 0,
      fiber: 0,
      sugar: 0,
      sodium: 0
    };
    
    dietRecords.forEach(record => {
      totalCalories += record.totalCalories || 0;
      
      // 累加营养素总量
      if (record.totalNutrition) {
        totalNutrition.protein += record.totalNutrition.protein || 0;
        totalNutrition.fat += record.totalNutrition.fat || 0;
        totalNutrition.carbohydrate += record.totalNutrition.carbohydrate || 0;
        totalNutrition.fiber += record.totalNutrition.fiber || 0;
        totalNutrition.sugar += record.totalNutrition.sugar || 0;
        totalNutrition.sodium += record.totalNutrition.sodium || 0;
      }
    });
    
    // 计算日均卡路里和营养素摄入
    const daysInPeriod = period === 'today' ? 1 : period === 'week' ? 7 : 30;
    const averageDailyCalories = Math.round(totalCalories / daysInPeriod);
    const nutritionAverage = {
      protein: Math.round(totalNutrition.protein / daysInPeriod * 10) / 10,
      fat: Math.round(totalNutrition.fat / daysInPeriod * 10) / 10,
      carbohydrate: Math.round(totalNutrition.carbohydrate / daysInPeriod * 10) / 10,
      fiber: Math.round(totalNutrition.fiber / daysInPeriod * 10) / 10,
      sugar: Math.round(totalNutrition.sugar / daysInPeriod * 10) / 10,
      sodium: Math.round(totalNutrition.sodium / daysInPeriod * 10) / 10
    };
    
    // 计算宏量营养素实际比例
    const totalMacro = totalNutrition.protein + totalNutrition.fat + totalNutrition.carbohydrate;
    const macroRatioActual = {
      protein: totalMacro > 0 ? Math.round((totalNutrition.protein / totalMacro) * 1000) / 10 : 0,
      fat: totalMacro > 0 ? Math.round((totalNutrition.fat / totalMacro) * 1000) / 10 : 0,
      carbohydrate: totalMacro > 0 ? Math.round((totalNutrition.carbohydrate / totalMacro) * 1000) / 10 : 0
    };
    
    // 计算目标完成度
    const goalCompletion = {};
    if (nutritionGoal) {
      goalCompletion.calories = Math.round((averageDailyCalories / nutritionGoal.caloriesGoal) * 100);
      
      if (nutritionGoal.nutritionGoals) {
        goalCompletion.protein = Math.round((nutritionAverage.protein / nutritionGoal.nutritionGoals.protein) * 100);
        goalCompletion.fat = Math.round((nutritionAverage.fat / nutritionGoal.nutritionGoals.fat) * 100);
        goalCompletion.carbohydrate = Math.round((nutritionAverage.carbohydrate / nutritionGoal.nutritionGoals.carbohydrate) * 100);
        goalCompletion.fiber = Math.round((nutritionAverage.fiber / nutritionGoal.nutritionGoals.fiber) * 100);
        goalCompletion.sugar = Math.round((nutritionAverage.sugar / nutritionGoal.nutritionGoals.sugar) * 100);
        goalCompletion.sodium = Math.round((nutritionAverage.sodium / nutritionGoal.nutritionGoals.sodium) * 100);
      }
    } else {
      // 默认目标值
      goalCompletion.calories = 0;
      goalCompletion.protein = 0;
      goalCompletion.fat = 0;
      goalCompletion.carbohydrate = 0;
      goalCompletion.fiber = 0;
      goalCompletion.sugar = 0;
      goalCompletion.sodium = 0;
    }
    
    // 生成每日数据
    const dailyData = [];
    
    // 按日期分组整合数据
    const dailyMap = {};
    dietRecords.forEach(record => {
      const date = moment(record.dateTime).format('YYYY-MM-DD');
      
      if (!dailyMap[date]) {
        dailyMap[date] = {
          date,
          totalCalories: 0,
          nutrition: {
            protein: 0,
            fat: 0,
            carbohydrate: 0,
            fiber: 0,
            sugar: 0,
            sodium: 0
          }
        };
      }
      
      dailyMap[date].totalCalories += record.totalCalories || 0;
      
      if (record.totalNutrition) {
        dailyMap[date].nutrition.protein += record.totalNutrition.protein || 0;
        dailyMap[date].nutrition.fat += record.totalNutrition.fat || 0;
        dailyMap[date].nutrition.carbohydrate += record.totalNutrition.carbohydrate || 0;
        dailyMap[date].nutrition.fiber += record.totalNutrition.fiber || 0;
        dailyMap[date].nutrition.sugar += record.totalNutrition.sugar || 0;
        dailyMap[date].nutrition.sodium += record.totalNutrition.sodium || 0;
      }
    });
    
    // 填充日期数据
    for (let i = 0; i < daysInPeriod; i++) {
      const date = moment(startDate).add(i, 'days').format('YYYY-MM-DD');
      if (dailyMap[date]) {
        dailyData.push(dailyMap[date]);
      } else {
        // 填充没有数据的日期
        dailyData.push({
          date,
          totalCalories: 0,
          nutrition: {
            protein: 0,
            fat: 0,
            carbohydrate: 0,
            fiber: 0,
            sugar: 0,
            sodium: 0
          }
        });
      }
    }
    
    // 计算趋势
    const calculateTrend = (values) => {
      if (values.length < 3) return 'insufficient_data';
      
      const lastThree = values.slice(-3);
      const firstThree = values.slice(0, 3);
      
      const lastThreeAvg = lastThree.reduce((sum, val) => sum + val, 0) / lastThree.length;
      const firstThreeAvg = firstThree.reduce((sum, val) => sum + val, 0) / firstThree.length;
      
      const difference = lastThreeAvg - firstThreeAvg;
      const threshold = firstThreeAvg * 0.05; // 5%变动阈值
      
      if (Math.abs(difference) < threshold) return 'steady';
      return difference > 0 ? 'increasing' : 'decreasing';
    };
    
    const trends = {
      caloriesTrend: calculateTrend(dailyData.map(day => day.totalCalories)),
      proteinTrend: calculateTrend(dailyData.map(day => day.nutrition.protein)),
      fatTrend: calculateTrend(dailyData.map(day => day.nutrition.fat)),
      carbohydrateTrend: calculateTrend(dailyData.map(day => day.nutrition.carbohydrate)),
      fiberTrend: calculateTrend(dailyData.map(day => day.nutrition.fiber))
    };
    
    // 生成建议
    const recommendations = [];
    
    // 蛋白质建议
    if (trends.proteinTrend === 'decreasing' && goalCompletion.protein < 90) {
      recommendations.push({
        type: '蛋白质补充',
        content: '您的蛋白质摄入趋势呈下降态势，且低于目标值。建议增加瘦肉、蛋类等优质蛋白质来源。'
      });
    } else if (goalCompletion.protein < 80) {
      recommendations.push({
        type: '蛋白质不足',
        content: '您的蛋白质摄入不足，仅达到目标的' + goalCompletion.protein + '%。建议适当增加鱼肉、豆制品等高蛋白食物。'
      });
    }
    
    // 脂肪建议
    if (trends.fatTrend === 'increasing' && goalCompletion.fat > 110) {
      recommendations.push({
        type: '脂肪控制',
        content: '您的脂肪摄入呈上升趋势，建议控制油脂的使用量，选择蒸煮等低脂烹饪方式。'
      });
    } else if (goalCompletion.fat > 120) {
      recommendations.push({
        type: '脂肪过量',
        content: '您的脂肪摄入超出目标' + (goalCompletion.fat - 100) + '%。建议减少油炸食品和高脂肪食物的摄入。'
      });
    }
    
    // 碳水化合物建议
    if (goalCompletion.carbohydrate > 120) {
      recommendations.push({
        type: '碳水控制',
        content: '您的碳水化合物摄入超出目标' + (goalCompletion.carbohydrate - 100) + '%。建议减少精制碳水如白米、白面和糖的摄入。'
      });
    }
    
    // 膳食纤维建议
    if (goalCompletion.fiber < 70) {
      recommendations.push({
        type: '膳食纤维补充',
        content: '您的膳食纤维摄入不足，建议增加全谷物、蔬菜、水果等富含膳食纤维的食物。'
      });
    }
    
    // 构建完整的分析结果
    const analysisResult = {
      userId,
      period,
      startDate: moment(startDate).format('YYYY-MM-DD'),
      endDate: moment(endDate).format('YYYY-MM-DD'),
      nutritionGoal: nutritionGoal ? {
        _id: nutritionGoal._id,
        caloriesGoal: nutritionGoal.caloriesGoal,
        nutritionGoals: nutritionGoal.nutritionGoals,
        macroRatio: nutritionGoal.macroRatio
      } : null,
      actual: {
        totalRecords: dietRecords.length,
        totalCalories,
        averageDailyCalories,
        nutritionTotal: totalNutrition,
        nutritionAverage,
        macroRatioActual
      },
      goalCompletion,
      dailyData,
      trends,
      recommendations
    };
    
    logger.info(`【营养分析】成功获取营养分析数据`);
    return analysisResult;
  } catch (error) {
    logger.error(`【营养分析】获取营养分析数据失败: ${error.message}`);
    throw error;
  }
};

module.exports = {
  getCaloriesTrend,
  getNutrientRatio,
  getNutrientDetails,
  getNutritionAnalysis
};